package com.example.demo.web;

import com.example.demo.config.response.ResponseResult;
import com.example.demo.model.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author topCombine
 * 线程测试
 */
@Api(tags = "多线程测试")
@RestController
@RequestMapping("/global/exception")
@Slf4j
public class JucController {

    /**
     * 线程数量
     */
    private static final Integer THREAD_COUNT = 10;

    @GetMapping("/testWithinThread")
    @ApiOperation(value = "普通请求(无多线程)")
    public List<User> testWithinThread() throws InterruptedException {
        List<User> userList = new ArrayList<>(THREAD_COUNT);

        Instant startTime = Instant.now();
        for (int i = 0; i < THREAD_COUNT; i++) {
            // 休眠2秒
            Thread.sleep(2000);
            userList.add(User.builder().id(i + "").userName(Thread.currentThread().getName()).build());
        }
        Instant endTime = Instant.now();

        log.info("耗时：{}毫秒", ChronoUnit.MILLIS.between(startTime, endTime));
        return userList;
    }

    @GetMapping("/testWithThread")
    @ApiOperation(value = "多线程请求")
    public List<User> testWithThread() throws InterruptedException, ExecutionException {
        List<User> userList = new ArrayList<>(THREAD_COUNT);

        // 创建线程池
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(THREAD_COUNT, THREAD_COUNT, 2, TimeUnit.SECONDS, new LinkedBlockingQueue<>(5));
        Instant startTime = Instant.now();
        List<Future> futureList = new ArrayList<>(THREAD_COUNT);
        for (int i = 0; i < THREAD_COUNT; i++) {
            // 执行(execute无返回结果；  submit有返回结果)
            Future future = poolExecutor.submit((Callable) () -> {
                // 休眠2秒
                Thread.sleep(2000);
                return User.builder().id("测试").userName(Thread.currentThread().getName()).build();
            });
            futureList.add(future);
        }
        // 解析结果
        for (Future future : futureList) {
            User user = ((User) future.get());
            userList.add(user);
        }
        // 结束多线程，保证都能取到值
        poolExecutor.shutdown();
        Instant endTime = Instant.now();

        log.info("耗时：{}毫秒", ChronoUnit.MILLIS.between(startTime, endTime));
        return userList;
    }


}
